package br.ucb.cm.board.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;

import br.ucb.cm.board.bean.Location;
import br.ucb.cm.board.bean.Move;
import br.ucb.cm.board.bean.Piece;
import br.ucb.cm.config.bean.PieceConfig;
import br.ucb.cm.main.ai.bean.MoveTreeNode;
import br.ucb.cm.main.common.GeneralConstants.PlayerEnum;

public class BoardUtil {
	public static PieceConfig getEnemyPiece(PieceConfig piece){
		return new PieceConfig(
				piece.getName(), 
				piece.getPoints(), 
				piece.getMoves(), 
				piece.getAttack(), 
				ImageEnum.getReverseImage(piece.getIcon())
				);
	}

	public static boolean isPlayerTwo(PieceConfig piece) {
		return ImageEnum.isPlayerTwoIcon(piece.getIcon());
	}

	public static boolean isPlayerOne(PieceConfig piece) {
		return ImageEnum.isPlayerOneIcon(piece.getIcon());
	}

	public static boolean isEnemy(PieceConfig pieceConfig, PlayerEnum playerEnum) {
		return (playerEnum == PlayerEnum.PLAYER_ONE) ? isPlayerTwo(pieceConfig) : isPlayerOne(pieceConfig);
	}

	public static List<Move> getMovesForPiece(Piece piece, Map<Location, PieceConfig> pieceMap){
		MovementUtil movementUtil = new MovementUtil(piece.getOwner(), MovementUtil.MOVE);
		List<Move> moveList = new ArrayList<Move>();

		moveList.addAll(movementUtil.verticalMoves(piece, pieceMap));
		moveList.addAll(movementUtil.horizontalMoves(piece, pieceMap));
		moveList.addAll(movementUtil.diagonalMoves(piece, pieceMap));

		return moveList;
	}

	public static List<Move> getAttacksForPiece(Piece piece, Map<Location, PieceConfig> pieceMap){
		MovementUtil movementUtil = new MovementUtil(piece.getOwner(), MovementUtil.ATTACK);
		List<Move> moveList = new ArrayList<Move>();

		moveList.addAll(movementUtil.verticalMoves(piece, pieceMap));
		moveList.addAll(movementUtil.horizontalMoves(piece, pieceMap));
		moveList.addAll(movementUtil.diagonalMoves(piece, pieceMap));

		return moveList;
	}
	
	public static List<Move> getAllMovesForPiece(Piece piece, Map<Location, PieceConfig> pieceMap){
		List<Move> moves = new ArrayList<Move>();
		
		moves.addAll(getMovesForPiece(piece, pieceMap));
		moves.addAll(getAttacksForPiece(piece, pieceMap));
		
		return moves;
	}
	
	public static List<Move> getAttacksForPieceList(List<Piece> pieces, PlayerEnum owner, Map<Location, PieceConfig> pieceMap){
		MovementUtil movementUtil = new MovementUtil(owner, MovementUtil.ATTACK);
		List<Move> moveList = new ArrayList<Move>();

		for (Piece piece : pieces) {
			moveList.addAll(movementUtil.verticalMoves(piece, pieceMap));
			moveList.addAll(movementUtil.horizontalMoves(piece, pieceMap));
			moveList.addAll(movementUtil.diagonalMoves(piece, pieceMap));
		}

		return moveList;
	}
	
	public static List<Move> getMovesForPieceList(List<Piece> pieces, PlayerEnum owner, Map<Location, PieceConfig> pieceMap){
		MovementUtil movementUtil = new MovementUtil(owner, MovementUtil.MOVE);
		List<Move> moveList = new ArrayList<Move>();

		for (Piece piece : pieces) {
			moveList.addAll(movementUtil.verticalMoves(piece, pieceMap));
			moveList.addAll(movementUtil.horizontalMoves(piece, pieceMap));
			moveList.addAll(movementUtil.diagonalMoves(piece, pieceMap));
		}

		return moveList;
	}

	public static List<Move> getAllMovesForPieceList(PlayerEnum owner, Map<Location, PieceConfig> pieceMap){
		List<Piece> pieces = mountPieceList(pieceMap, owner);
		List<Move> moves = new ArrayList<Move>();
		
		moves.addAll(getMovesForPieceList(pieces, owner, pieceMap));
		moves.addAll(getAttacksForPieceList(pieces, owner, pieceMap));
		
		return moves;
	}

	public static PlayerEnum getOwner(PieceConfig piece){
		if(isPlayerOne(piece))
			return PlayerEnum.PLAYER_ONE;
		else 
			return PlayerEnum.PLAYER_TWO;
	}

	public static void playSound(SampleEnum sample) {
		try {
			AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(BoardUtil.class.getResource(sample.getResourcePath()));
			Clip clip = AudioSystem.getClip();
			clip.open(audioInputStream);
			clip.start();
		} catch(Exception ex) {
			System.out.println("Error with playing sound.");
			ex.printStackTrace();
		}
	}

	public static List<Piece> mountPieceList(Map<Location, PieceConfig> map, PlayerEnum player){
		List<Piece> pieces = new ArrayList<Piece>();

		for (Entry<Location, PieceConfig> entry : map.entrySet()) {
			if((player == PlayerEnum.PLAYER_ONE && BoardUtil.isPlayerOne(entry.getValue())) ||
					(player == PlayerEnum.PLAYER_TWO && BoardUtil.isPlayerTwo(entry.getValue())))
				pieces.add(new Piece(entry.getValue(), entry.getKey(), player));
		}

		return pieces;
	}
	
	public MoveTreeNode mountMoveTree(Map<Location, PieceConfig> pieceMap, PlayerEnum player, Move move, int level){
		return null;
	}
}
